import 'dart:io';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:kq_flutter_core_widget/utils/ex/kq_ex.dart';
import 'package:kq_flutter_core_widget/widgets/button/kq_ink_well.dart';

import '../../config/kq_core_global.dart';
import '../../resources/images.dart';
import 'oss_image.dart';

/// 通用图片展示
///
/// @author 周卓
///
/// 支持file、http、oss、assets
class KqImage extends StatefulWidget {
  /// 图片宽度，外层没有约束的时候是控件的宽度，同时还用于获取下载OSS图片的宽度
  final double? width;

  /// 图片高度，外层没有约束的时候是控件的高度，同时还用于获取下载OSS图片的高度
  final double? height;

  /// 图片裁剪圆角，默认0
  final double radius;

  /// 图片类型，支持 [ImageType.oss]、 [ImageType.http]、[ImageType.assets]、[ImageType.file]，默认[ImageType.oss]
  final ImageType imageType;

  /// 加载中的图片的assets路径，仅对[ImageType.oss]和[ImageType.http]有效。如果传了[placeholderBuilder]则此值无效
  final String? placeHolder;

  /// 图片未加载之前显示内容构建器，仅对[ImageType.oss]和[ImageType.http]有效
  final PlaceholderWidgetBuilder? placeholderBuilder;

  /// 错误的图片的assets路径，仅对[ImageType.oss]、[ImageType.http]和[ImageType.file]有效。如果传了[errorImageBuilder]则此值无效
  final String? errorImage;

  /// 图片加载失败时显示的组件，仅对[ImageType.oss]、[ImageType.http]和[ImageType.file]有效
  final ErrorWidgetBuilder? errorImageBuilder;

  /// 图片url，包括ossKey，http链接，filePath，assetPath
  final String url;

  /// 图片缩放类型
  final BoxFit? fit;

  /// 图片颜色
  final Color? color;

  /// 背景颜色
  final Color backgroundColor;

  /// 边框颜色
  final Color borderColor;

  /// 边框宽度
  final double borderWidth;

  /// 图片混合模式，结合[color] 使用
  final BlendMode? colorBlendMode;

  /// 包名，如果应用组件库内部图片，需要使用[KqCoreGlobal.packageName]
  final String? package;

  /// 点击回调
  final Function(ImageType imageType, BoxFit? fit, String url)? onTap;

  final String? tag;

  /// 默认类型oss
  const KqImage.oss(
      {Key? key,
      required this.url,
      this.fit,
      this.radius = 0,
      required this.width,
      required this.height,
      this.placeHolder,
      this.borderWidth = 0,
      this.borderColor = Colors.transparent,
      this.placeholderBuilder,
      this.package,
      this.color,
      this.backgroundColor = Colors.transparent,
      this.colorBlendMode,
      this.onTap,
      this.tag,
      this.errorImage,
      this.errorImageBuilder})
      : imageType = ImageType.oss,
        assert(width != null && height != null,
            'imageType=ImageType.oss时，width和height必传'),
        super(key: key);

  /// 默认类型http
  const KqImage.http(
      {Key? key,
      required this.url,
      this.fit,
      this.radius = 0,
      this.width,
      this.height,
      this.placeHolder,
      this.borderWidth = 0,
      this.borderColor = Colors.transparent,
      this.placeholderBuilder,
      this.package,
      this.color,
      this.backgroundColor = Colors.transparent,
      this.colorBlendMode,
      this.onTap,
      this.tag,
      this.errorImage,
      this.errorImageBuilder})
      : imageType = ImageType.http,
        super(key: key);

  /// 默认类型file
  const KqImage.file(
      {Key? key,
      required this.url,
      this.fit,
      this.radius = 0,
      this.width,
      this.height,
      this.placeHolder,
      this.borderWidth = 0,
      this.borderColor = Colors.transparent,
      this.placeholderBuilder,
      this.package,
      this.color,
      this.backgroundColor = Colors.transparent,
      this.colorBlendMode,
      this.onTap,
      this.tag,
      this.errorImage,
      this.errorImageBuilder})
      : imageType = ImageType.file,
        super(key: key);

  /// 默认类型assets
  const KqImage.assets(
      {Key? key,
      required this.url,
      this.fit,
      this.radius = 0,
      this.width,
      this.height,
      this.placeHolder,
      this.borderWidth = 0,
      this.borderColor = Colors.transparent,
      this.placeholderBuilder,
      this.package,
      this.color,
      this.backgroundColor = Colors.transparent,
      this.colorBlendMode,
      this.onTap,
      this.tag,
      this.errorImage,
      this.errorImageBuilder})
      : imageType = ImageType.assets,
        super(key: key);

  /// 自定义类型
  const KqImage.custom(
      {Key? key,
      required this.url,
      required this.imageType,
      this.fit,
      this.radius = 0,
      this.width,
      this.height,
      this.placeHolder,
      this.borderWidth = 0,
      this.borderColor = Colors.transparent,
      this.placeholderBuilder,
      this.package,
      this.color,
      this.backgroundColor = Colors.transparent,
      this.colorBlendMode,
      this.onTap,
      this.tag,
      this.errorImage,
      this.errorImageBuilder})
      : assert(imageType != ImageType.oss || (width != null && height != null),
            'imageType=ImageType.oss时，width和height必传'),
        super(key: key);

  @override
  State<KqImage> createState() => _KqImageState();
}

class _KqImageState extends State<KqImage> {
  Widget _buildImage(BuildContext context) {
    var url = widget.url;
    if (url.isNullOrEmpty) {
      return _builderError(context, "url为空");
    }
    if (url.startsWith("http://") ||
        url.startsWith("https://") ||
        widget.imageType == ImageType.http) {
      return CachedNetworkImage(
        imageUrl: url,
        color: widget.color,
        colorBlendMode: widget.colorBlendMode,
        placeholder:
            widget.placeholderBuilder ?? (context, url) => _buildPlaceHolder(),
        errorWidget: widget.errorImageBuilder ??
            (context, url, error) => _builderError(context, error),
        width: widget.width,
        height: widget.height,
        fit: widget.fit ?? BoxFit.cover,
      );
    } else if (widget.imageType == ImageType.file) {
      return Image.file(File(url),
          width: widget.width,
          height: widget.height,
          color: widget.color,
          colorBlendMode: widget.colorBlendMode,
          errorBuilder: (context, error, stackTrace) =>
              _builderError(context, error),
          fit: widget.fit ?? BoxFit.cover);
    } else if (widget.imageType == ImageType.oss) {
      return OssImage(
          ossKey: url,
          placeHolder: widget.placeHolder,
          placeholderBuilder: widget.placeholderBuilder,
          errorImage: widget.errorImage,
          errorImageBuilder: widget.errorImageBuilder,
          width: widget.width!,
          height: widget.height!,
          color: widget.color,
          colorBlendMode: widget.colorBlendMode,
          fit: widget.fit ?? BoxFit.cover,
          tag: widget.tag,
          package: widget.package);
    } else {
      return Image.asset(
        url,
        width: widget.width,
        height: widget.height,
        errorBuilder: (context, error, stackTrace) =>
            _builderError(context, error),
        color: widget.color,
        colorBlendMode: widget.colorBlendMode,
        fit: widget.fit ?? BoxFit.cover,
        package: widget.package,
      );
    }
  }

  /// 占位图片
  Widget _buildPlaceHolder() {
    return Image.asset(
      widget.placeHolder ?? Images.commonPicJinshuYuanjiao44,
      width: widget.width,
      height: widget.height,
      fit: widget.fit ?? BoxFit.cover,
      package: widget.placeHolder != null
          ? widget.package
          : KqCoreGlobal.packageName,
    );
  }

  /// 错误图片
  Widget _builderError(BuildContext context, dynamic error) {
    if (widget.errorImageBuilder != null) {
      return widget.errorImageBuilder!.call(context, widget.url, error);
    }

    return Image.asset(
      widget.errorImage ?? Images.commonPicJinshuYuanjiao44,
      width: widget.width,
      height: widget.height,
      fit: widget.fit ?? BoxFit.cover,
      package:
          widget.errorImage != null ? widget.package : KqCoreGlobal.packageName,
    );
  }

  @override
  Widget build(BuildContext context) {
    return KqInkWell(
      onTap: widget.onTap == null
          ? null
          : () {
              widget.onTap?.call(widget.imageType, widget.fit, widget.url);
            },
      backgroundColor: widget.backgroundColor,
      borderWidth: widget.borderWidth,
      borderColor: widget.borderColor,
      radius: widget.radius,
      child: ClipRRect(
        borderRadius: BorderRadius.all(Radius.circular(widget.radius)),
        child: _buildImage(context),
      ),
    );
  }
}

/// 图片类型
enum ImageType {
  /// 文件
  file,

  /// 项目内图片
  assets,

  /// 网络
  http,

  /// oss
  oss,
}

/// 图片加载失败时显示的组件构建器
typedef ErrorWidgetBuilder = Widget Function(
  BuildContext context,
  String url,
  dynamic error,
);
